package com.zhao.dota.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhao.dota.bo.PlayerMatchSummary;
import com.zhao.dota.bo.PlayerMax;
import com.zhao.dota.bo.PlayerPeers;
import com.zhao.dota.contant.PerformanceFieldConst;
import com.zhao.dota.model.MatchPlayer;
import com.zhao.dota.model.Performance;
import com.zhao.dota.model.Player;
import com.zhao.dota.service.MatchPlayerService;
import com.zhao.dota.service.MatchService;
import com.zhao.dota.service.PerformanceService;
import com.zhao.dota.service.PlayerService;
import com.zhao.dota.struct.Result;
import com.zhao.dota.util.SteamUtil;
import com.zhao.dota.vo.HeroWinRate;
import com.zhao.dota.vo.TotalsVo;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/player")
public class PlayerController {

    @Resource
    private PlayerService playerService;
    @Resource
    private MatchPlayerService matchPlayerService;
    @Resource
    private PerformanceService performanceService;
    @Resource
    private MatchService matchService;

    @GetMapping("/")
    public Result<Page<Player>> search(@Validated @NonNull String search) {
        Page<Player> result = playerService.search(search, new Page<>());
        return Result.success(result);
    }

    @GetMapping("/{id}")
    public Result<Player> detail(@PathVariable Integer id) {
        Player player = playerService.getById(id);
        return Result.success(player);
    }

    @GetMapping("/totals")
    public Result total(Integer id, Integer limit) {
        if (limit == null || limit == 0) {
            limit = -1;
        }
        Player player = playerService.getById(id);
        MatchPlayer matchCount = matchPlayerService.count(player, limit);
        Performance performance = performanceService.countByPlayer(player, limit);
        Double totalTimes = matchService.countTimeBySteamId(player.getSteamId(), limit);
        TotalsVo totalsVo = new TotalsVo();
        BeanUtils.copyProperties(performance, totalsVo);
        totalsVo.setWins(matchCount.getWin());
        totalsVo.setTotalMatches(matchCount.getMatchId());
        totalsVo.setTotalTimes(totalTimes);
        return Result.success(totalsVo);
    }

    @GetMapping("/recentMatchs")
    public Result<Page<PlayerMatchSummary>> recentMatches(Integer id, Page page) {
        Player player = playerService.getById(id);
        Page<PlayerMatchSummary> result = matchPlayerService.page(page, player.getSteamId());
        result.getRecords().forEach(s -> {
            s.setHeroAvatar(SteamUtil.getIconUrlByHeroName(s.getHeroName()));
            s.setHeroAvatarFull(SteamUtil.getIconUrlByHeroName(s.getHeroName()));
        });
        return Result.success(result);
    }

    @GetMapping("/heroes")
    public Result<Page<HeroWinRate>> hero(Integer playerId, Page page) {
        Page<HeroWinRate> heroWinRatePage = matchPlayerService.groupByPlayerHero(playerId, page);
        heroWinRatePage.getRecords().forEach(HeroWinRate::setHeroAvatar);
        return Result.success(heroWinRatePage);
    }

    @GetMapping("/peers")
    public Result peers(Integer id, @RequestParam(defaultValue = "6", required = false) Integer limit) {
        Player player = playerService.getById(id);
        Page page = new Page();
        page.setSize(limit);
        Page<PlayerPeers> peers = matchPlayerService.peersOrEnemies(page, player.getSteamId(), true);
        return Result.success(peers);
    }

    @GetMapping("/enemies")
    public Result enemies(Integer id, @RequestParam(defaultValue = "6", required = false) Integer limit) {
        Player player = playerService.getById(id);
        Page page = new Page();
        page.setSize(limit);
        Page<PlayerPeers> enemies = matchPlayerService.peersOrEnemies(page, player.getSteamId(), false);
        return Result.success(enemies);
    }

    @GetMapping("/maxs")
    public Result max(Integer id) {
        Player player = playerService.getById(id);
        Map<String, PlayerMax> maxMap = Arrays.stream(PerformanceFieldConst.values()).map(f -> {
            PlayerMax max = performanceService.max(f, player.getSteamId());
            if (max == null) {
                return null;
            }
            max.setField(f.name());
            max.buildHeroAvatar();
            return max;
        }).filter(Objects::nonNull).parallel()
                .collect(Collectors.toConcurrentMap(PlayerMax::getField, Function.identity()));
        return Result.success(maxMap);
    }

}
